package cn.edu.zut.qixiang.mock;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;

/**
 * 气压数据采集表数据生成器
 * 为气压数据采集站生成模拟数据（每隔10分钟采集一次）
 * @author 86178
 */
public class PressureDataGenerator {

    // 数据库配置
    private static final String URL = "jdbc:mysql://localhost:3306/qixiang_base?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8";
    private static final String USER = "root";
    private static final String PASSWORD = "520521fcf..@1234";

    // 数据生成参数
    private static final int BATCH_SIZE = 100;
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        generatePressureData();
    }

    /**
     * 生成气压数据（每隔10分钟采集一次）
     */
    public static void generatePressureData() {
        String selectStationsSql = "SELECT station_id FROM collection_stations WHERE station_type = '气压数据采集站' ORDER BY station_id";
        String insertDataSql = "INSERT INTO pressure_data (collection_station_id, pressure, collection_time) VALUES (?, ?, ?)";

        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             PreparedStatement selectStmt = conn.prepareStatement(selectStationsSql);
             PreparedStatement insertStmt = conn.prepareStatement(insertDataSql)) {

            conn.setAutoCommit(false);
            Random random = new Random();

            // 获取所有气压数据采集站
            ResultSet stationRs = selectStmt.executeQuery();

            int batchCount = 0;
            int totalRecords = 0;
            int stationCount = 0;

            // 生成2025年5月1日到9月1日的数据，每10分钟一次
            LocalDateTime startTime = LocalDateTime.of(2025, 5, 1, 0, 0, 0);
            LocalDateTime endTime = LocalDateTime.of(2025, 9, 1, 23, 50, 0);

            System.out.println("开始生成气压数据...");
            System.out.println("时间范围: " + startTime.format(DATE_FORMATTER) + " 到 " + endTime.format(DATE_FORMATTER));
            System.out.println("采集频率: 每10分钟一次");

            // 遍历每个气压采集站
            while (stationRs.next()) {
                int stationId = stationRs.getInt("station_id");
                stationCount++;
                System.out.println("为采集站 " + stationId + " 生成数据...");

                LocalDateTime currentTime = startTime;

                // 为每个时间点生成数据（每10分钟一次）
                while (!currentTime.isAfter(endTime)) {
                    // 生成气压数据
                    double pressure = generatePressure(currentTime, random, stationId);

                    // 设置插入参数
                    insertStmt.setInt(1, stationId);
                    insertStmt.setDouble(2, pressure);
                    insertStmt.setString(3, currentTime.format(DATE_FORMATTER));

                    insertStmt.addBatch();
                    batchCount++;
                    totalRecords++;

                    // 批量提交
                    if (batchCount % BATCH_SIZE == 0) {
                        insertStmt.executeBatch();
                        conn.commit();
                        System.out.println("已提交 " + batchCount + " 条记录，总计 " + totalRecords + " 条");
                    }

                    // 时间增加10分钟
                    currentTime = currentTime.plusMinutes(10);
                }
            }

            // 提交剩余数据
            if (batchCount % BATCH_SIZE != 0) {
                insertStmt.executeBatch();
                conn.commit();
            }

            System.out.println("气压数据生成完成！");
            System.out.println("共为 " + stationCount + " 个采集站生成 " + totalRecords + " 条记录");

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成气压数据
     * 模拟真实的气压变化模式：日变化、季节变化、天气系统影响
     */
    private static double generatePressure(LocalDateTime time, Random random, int stationId) {
        int month = time.getMonthValue();
        int hour = time.getHour();
        int minute = time.getMinute();

        // 基准气压（郑州地区正常气压范围）
        double basePressure = 1013.0;

        // 季节变化（夏季气压稍低，冬季气压稍高）
        double seasonalAdjustment = 0.0;
        switch (month) {
            case 5: // 5月
                seasonalAdjustment = -2.0;
                break;
            case 6: // 6月
                seasonalAdjustment = -4.0;
                break;
            case 7: // 7月
                seasonalAdjustment = -6.0;
                break;
            case 8: // 8月
                seasonalAdjustment = -5.0;
                break;
            case 9: // 9月
                seasonalAdjustment = -3.0;
                break;
        }

        // 日变化（气压在一天中有两个高峰和两个低谷）
        double diurnalVariation = calculateDiurnalVariation(hour, minute);

        // 天气系统影响（模拟高低压系统）
        double weatherSystemEffect = calculateWeatherSystemEffect(time, random);

        // 站点差异（不同站点有微小差异）
        double stationVariation = (stationId % 10) * 0.3;

        // 随机波动
        double randomFluctuation = (random.nextDouble() - 0.5) * 1.5;

        // 计算最终气压
        double pressure = basePressure + seasonalAdjustment + diurnalVariation +
                weatherSystemEffect + stationVariation + randomFluctuation;

        return Math.round(pressure * 10) / 10.0;
    }

    /**
     * 计算气压的日变化
     * 气压在一天中有两个高峰（10时和22时）和两个低谷（4时和16时）
     */
    private static double calculateDiurnalVariation(int hour, int minute) {
        double timeOfDay = hour + minute / 60.0;

        // 使用正弦函数模拟日变化
        double variation = Math.sin((timeOfDay - 10) * Math.PI / 12) * 1.5;

        return variation;
    }

    /**
     * 计算天气系统对气压的影响
     * 模拟高压系统和低压系统的交替出现
     */
    private static double calculateWeatherSystemEffect(LocalDateTime time, Random random) {
        // 使用日期作为种子，使同一日期的天气系统一致
        long daySeed = time.toLocalDate().toEpochDay();
        Random dayRandom = new Random(daySeed);

        // 模拟持续数天的天气系统
        int systemType = dayRandom.nextInt(3); // 0:正常, 1:高压, 2:低压

        switch (systemType) {
            case 1: // 高压系统
                return 8.0 + (dayRandom.nextDouble() - 0.5) * 4.0;
            case 2: // 低压系统
                return -12.0 + (dayRandom.nextDouble() - 0.5) * 6.0;
            default: // 正常
                return (dayRandom.nextDouble() - 0.5) * 3.0;
        }
    }
}